#pragma once

#include <iostream>
#include <unistd.h>
#include <queue>
#include <pthread.h>


#define NUM 5

//线程池
template<class T>
class threadpool{
    private:
    bool isEmpty(){
        return _task_qe.empty();
    }
    void LockQe(){
        pthread_mutex_lock(&_mutex);
    }
    void UnlockQe(){
        pthread_mutex_unlock(&_mutex);
    }
    void Wait(){
        pthread_cond_wait(&_cond,&_mutex);
    }
    void Notify(){
        pthread_cond_signal(&_cond);
    }
    public:
    threadpool(int num):_num(num){
        pthread_mutex_init(&_mutex);
        pthread_cond_init(&_cond);
    }
    ~threadpool(){
        pthread_cond_destroy(&_cond);
        pthread_mutex_destroy(&_mutex);
    }
    //向任务队列push
    void push(const T& task){
        LockQe();
        _task_qe.push(task);
        UnlockQe();
        //唤醒一个线程。
        Notify();
    }
    //从任务队列Pop(线程池中的线程调用)
    void pop(T& task){
        //因为每次只有一个线程会被唤醒所以不用担心线程安全问题。
        task = _task_qe.front();
        _task_qe.pop();
    }
    void threadpoolInit(){
        pthread_t tid;
        //因为主逻辑中创建就detach所以不用关心tid是什么
        for(int i = 0;i<_num;++i){
            pthread_create(&tid,nullptr,rountine,this);//this指针就可以让routine获取到private变量
        }
    }
    //线程要执行的逻辑
    static void* rountine(void* arg){
        pthread_detach(pthread_self());
        threadpool* self = (threadpool*) arg;
        while(1){
            self->LockQe();
            while(self->isEmpty()){
                self->Wait();
            }
            T task;
            self->pop(task);
            self->UnlockQe();

            task.run();//执行任务
        }
    }
    private:
    std::queue<T> _task_qe;//任务队列
    int _num;//线程数量
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
};